/**
 * Generate code from /{{projectName}}-core/src/main/java/{{packageName}}/core/{{modules}}/service/impl/Abstract{{entities@SQL}}Service.java.hbs
 */
package cn.ibizlab.core.ad.service.impl;

import java.util.*;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.util.*;
import cn.ibizlab.util.errors.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.context.annotation.Lazy;
import cn.ibizlab.core.ad.domain.SysOrganizationalRole;
import cn.ibizlab.core.ad.filter.SysOrganizationalRoleSearchContext;
import cn.ibizlab.core.ad.service.SysOrganizationalRoleService;
import cn.ibizlab.core.ad.mapper.SysOrganizationalRoleMapper;
import cn.ibizlab.util.enums.Entities;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import cn.ibizlab.core.ad.domain.SysDepartment;
import cn.ibizlab.core.ad.service.SysDepartmentService;
import cn.ibizlab.core.ad.domain.SysOrganizationalUnit;
import cn.ibizlab.core.ad.service.SysOrganizationalUnitService;
import cn.ibizlab.core.ad.domain.SysOrganization;
import cn.ibizlab.core.ad.service.SysOrganizationService;
import cn.ibizlab.core.ad.domain.SysMember;
import cn.ibizlab.core.ad.service.SysMemberService;
import cn.ibizlab.core.ad.domain.SysGroupOfNames;
import cn.ibizlab.core.ad.service.SysGroupOfNamesService;

/**
 * 实体[用户组] 服务对象接口实现
 *
 * @author generator
 */
@Slf4j
public abstract class AbstractSysOrganizationalRoleService extends ServiceImpl<SysOrganizationalRoleMapper,SysOrganizationalRole> implements SysOrganizationalRoleService {

    @Autowired
    @Lazy
    protected SysDepartmentService sysDepartmentService;

    @Autowired
    @Lazy
    protected SysOrganizationalUnitService sysOrganizationalUnitService;

    @Autowired
    @Lazy
    protected SysOrganizationService sysOrganizationService;

    @Autowired
    @Lazy
    protected SysMemberService sysMemberService;

    @Autowired
    @Lazy
    protected SysGroupOfNamesService sysGroupOfNamesService;

    @Autowired
    @Lazy
    protected cn.ibizlab.core.ad.mapping.SysOrganizationalRoleInheritMapping sysOrganizationalRoleInheritMapping;

    protected int batchSize = 500;

    public SysOrganizationalRole get(SysOrganizationalRole et) {
        SysOrganizationalRole rt = this.baseMapper.selectEntity(et);
        if(rt == null)
            throw new NotFoundException("数据不存在",Entities.SYS_ORGANIZATIONAL_ROLE.toString(),et.getId());
        rt.copyTo(et,true);
        //设置 [成员]
        getMember(et);
        return et;
    }

    public List<SysOrganizationalRole> getByEntities(List<SysOrganizationalRole> entities) {
        return this.baseMapper.selectEntities(entities);
    }

    public void fillParentData(SysOrganizationalRole et) {
        if(Entities.SYS_DEPARTMENT.equals(et.getContextParentEntity()) && et.getContextParentKey()!=null) {
            et.setDepartmentId((String)et.getContextParentKey());
        }
        if(!ObjectUtils.isEmpty(et.getDepartmentId())) {
            SysDepartment sysDepartment = et.getDepartment();
            if(sysDepartment == null) {
                sysDepartment = sysDepartmentService.getById(et.getDepartmentId());
                et.setDepartment(sysDepartment);
            }
            if(!ObjectUtils.isEmpty(sysDepartment)) {
                et.setDepartmentId(sysDepartment.getId());
                et.setDepartmentName(sysDepartment.getDepartmentName());
                et.setDepartmentNumber(sysDepartment.getDepartmentNumber());
                et.setOrganizationId(sysDepartment.getOrganizationId());
                et.setOrganizationName(sysDepartment.getOrganizationName());
                et.setOrganizationNumber(sysDepartment.getOrganizationNumber());
            }
        }
        if(Entities.SYS_ORGANIZATIONAL_UNIT.equals(et.getContextParentEntity()) && et.getContextParentKey()!=null) {
            et.setOrganizationalUnitId((String)et.getContextParentKey());
        }
        if(Entities.SYS_ORGANIZATION.equals(et.getContextParentEntity()) && et.getContextParentKey()!=null) {
            et.setOrganizationId((String)et.getContextParentKey());
        }
    }

    public SysOrganizationalRole getDraft(SysOrganizationalRole et) {
        fillParentData(et);
        return et;
    }

    public Integer checkKey(SysOrganizationalRole et) {
        fillParentData(et);
        return (!ObjectUtils.isEmpty(et.getId()) && this.count(Wrappers.<SysOrganizationalRole>lambdaQuery().eq(SysOrganizationalRole::getId, et.getId()))>0)?1:0;
    }

    @Override
    @Transactional
    public boolean create(SysOrganizationalRole et) {
        fillParentData(et);
        if(this.baseMapper.insert(et) < 1)
            return false;
        sysMemberService.saveByOrganizationalRole(et,et.getMember());
        get(et);
        return true;
    }

    @Transactional
    public boolean createBatch(List<SysOrganizationalRole> list) {
        list.forEach(et->getSelf().create(et));
        return true;
    }

    @Transactional
    public boolean update(SysOrganizationalRole et) {
        fillParentData(et);
        UpdateWrapper<SysOrganizationalRole> qw = et.getUpdateWrapper(true);
        qw.eq("id", et.getId());
        if(!update(et, qw))
            return false;
        sysMemberService.saveByOrganizationalRole(et,et.getMember());
        get(et);
        return true;
    }

    @Transactional
    public boolean updateBatch(List<SysOrganizationalRole> list) {
        list.forEach(et->getSelf().update(et));
        return true;
    }

    @Override
    @Transactional
    public boolean save(SysOrganizationalRole et) {
        if(checkKey(et) > 0)
            return getSelf().update(et);
        else
            return getSelf().create(et);
    }

    @Transactional
    public boolean saveBatch(List<SysOrganizationalRole> list) {
        if(ObjectUtils.isEmpty(list))
            return true;
        Map<String,SysOrganizationalRole> before = getByEntities(list).stream().collect(Collectors.toMap(SysOrganizationalRole::getId,e->e));
        List<SysOrganizationalRole> create = new ArrayList<>();
        List<SysOrganizationalRole> update = new ArrayList<>();
        list.forEach(sub->{
            if(!ObjectUtils.isEmpty(sub.getId()) && before.containsKey(sub.getId()))
                update.add(sub);
            else
                create.add(sub);
        });
        if(!update.isEmpty())
            update.forEach(item->this.getSelf().update(item));
        if(!create.isEmpty() && !getSelf().createBatch(create))
            return false;
        else
            return true;
    }

    @Transactional
    public boolean remove(SysOrganizationalRole et) {
        String key = et.getId();
        sysMemberService.removeByOrganizationalRoleId(key);
        if(!remove(Wrappers.<SysOrganizationalRole>lambdaQuery().eq(SysOrganizationalRole::getId, et.getId())))
            return false;
        return true;
    }

    @Transactional
    public boolean removeByEntities(List<SysOrganizationalRole> entities) {
        for (SysOrganizationalRole et : entities)
            if(!getSelf().remove(et))
                return false;
        return true;
    }

    public Page<SysOrganizationalRole> searchCurPersonGroup(SysOrganizationalRoleSearchContext context) {
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<SysOrganizationalRole> pages=baseMapper.searchCurPersonGroup(context.getPages(),context,context.getSelectCond());
        List<SysOrganizationalRole> list = pages.getRecords();
        return new PageImpl<>(list, context.getPageable(), pages.getTotal());
    }

    public List<SysOrganizationalRole> listCurPersonGroup(SysOrganizationalRoleSearchContext context) {
        List<SysOrganizationalRole> list = baseMapper.listCurPersonGroup(context,context.getSelectCond());
        return list;
    }

    public Page<SysOrganizationalRole> searchDefault(SysOrganizationalRoleSearchContext context) {
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<SysOrganizationalRole> pages=baseMapper.searchDefault(context.getPages(),context,context.getSelectCond());
        List<SysOrganizationalRole> list = pages.getRecords();
        return new PageImpl<>(list, context.getPageable(), pages.getTotal());
    }

    public List<SysOrganizationalRole> listDefault(SysOrganizationalRoleSearchContext context) {
        List<SysOrganizationalRole> list = baseMapper.listDefault(context,context.getSelectCond());
        return list;
    }

    public List<SysOrganizationalRole> findByDepartmentId(List<String> departmentIds) {
        List<SysOrganizationalRole> list = baseMapper.findByDepartmentId(departmentIds);
        if(!ObjectUtils.isEmpty(list))
            sysMemberService.findByOrganizationalRoleId(list.stream().map(e->e.getId()).collect(Collectors.toList()))
                .stream().collect(Collectors.groupingBy(e->e.getOrganizationalRoleId())).entrySet().forEach(sub->list.stream().filter(item->item.getId().equals(sub.getKey())).findFirst().ifPresent(item->item.setMember(sub.getValue())));
        return list;
    }

    public List<SysOrganizationalRole> findByOrganizationalUnitId(List<String> organizationalUnitIds) {
        List<SysOrganizationalRole> list = baseMapper.findByOrganizationalUnitId(organizationalUnitIds);
        if(!ObjectUtils.isEmpty(list))
            sysMemberService.findByOrganizationalRoleId(list.stream().map(e->e.getId()).collect(Collectors.toList()))
                .stream().collect(Collectors.groupingBy(e->e.getOrganizationalRoleId())).entrySet().forEach(sub->list.stream().filter(item->item.getId().equals(sub.getKey())).findFirst().ifPresent(item->item.setMember(sub.getValue())));
        return list;
    }

    public List<SysOrganizationalRole> findByOrganizationId(List<String> organizationIds) {
        List<SysOrganizationalRole> list = baseMapper.findByOrganizationId(organizationIds);
        if(!ObjectUtils.isEmpty(list))
            sysMemberService.findByOrganizationalRoleId(list.stream().map(e->e.getId()).collect(Collectors.toList()))
                .stream().collect(Collectors.groupingBy(e->e.getOrganizationalRoleId())).entrySet().forEach(sub->list.stream().filter(item->item.getId().equals(sub.getKey())).findFirst().ifPresent(item->item.setMember(sub.getValue())));
        return list;
    }

    public boolean removeByDepartmentId(String departmentId) {
        List<String> ids = baseMapper.findByDepartmentId(Arrays.asList(departmentId)).stream().map(e->e.getId()).collect(Collectors.toList());
        if(!ObjectUtils.isEmpty(ids))
            return this.removeBatch(ids);
        else
            return true;
    }

    public boolean resetByDepartmentId(String departmentId) {
        return this.update(Wrappers.<SysOrganizationalRole>lambdaUpdate().eq(SysOrganizationalRole::getDepartmentId,departmentId));
    }

    public boolean saveByDepartment(SysDepartment sysDepartment,List<SysOrganizationalRole> list) {
        if(list==null)
            return true;
        Map<String,SysOrganizationalRole> before = findByDepartmentId(sysDepartment.getId()).stream().collect(Collectors.toMap(SysOrganizationalRole::getId,e->e));
        List<SysOrganizationalRole> update = new ArrayList<>();
        List<SysOrganizationalRole> create = new ArrayList<>();

        for(SysOrganizationalRole sub:list) {
            sub.setDepartmentId(sysDepartment.getId());
            sub.setDepartment(sysDepartment);
            if(!ObjectUtils.isEmpty(sub.getId())&&before.containsKey(sub.getId())) {
                before.remove(sub.getId());
                update.add(sub);
            }
            else
                create.add(sub);
        }
        if(!update.isEmpty())
            update.forEach(item->this.getSelf().update(item));
        if(!create.isEmpty() && !getSelf().createBatch(create))
            return false;
        else if(!before.isEmpty() && !getSelf().removeBatch(before.keySet()))
            return false;
        else
            return true;
    }

    public boolean removeByOrganizationalUnitId(String organizationalUnitId) {
        List<String> ids = baseMapper.findByOrganizationalUnitId(Arrays.asList(organizationalUnitId)).stream().map(e->e.getId()).collect(Collectors.toList());
        if(!ObjectUtils.isEmpty(ids))
            return this.removeBatch(ids);
        else
            return true;
    }

    public boolean resetByOrganizationalUnitId(String organizationalUnitId) {
        return this.update(Wrappers.<SysOrganizationalRole>lambdaUpdate().eq(SysOrganizationalRole::getOrganizationalUnitId,organizationalUnitId));
    }

    public boolean saveByOrganizationalUnit(SysOrganizationalUnit sysOrganizationalUnit,List<SysOrganizationalRole> list) {
        if(list==null)
            return true;
        Map<String,SysOrganizationalRole> before = findByOrganizationalUnitId(sysOrganizationalUnit.getId()).stream().collect(Collectors.toMap(SysOrganizationalRole::getId,e->e));
        List<SysOrganizationalRole> update = new ArrayList<>();
        List<SysOrganizationalRole> create = new ArrayList<>();

        for(SysOrganizationalRole sub:list) {
            sub.setOrganizationalUnitId(sysOrganizationalUnit.getId());
            sub.setOrganizationalUnit(sysOrganizationalUnit);
            if(!ObjectUtils.isEmpty(sub.getId())&&before.containsKey(sub.getId())) {
                before.remove(sub.getId());
                update.add(sub);
            }
            else
                create.add(sub);
        }
        if(!update.isEmpty())
            update.forEach(item->this.getSelf().update(item));
        if(!create.isEmpty() && !getSelf().createBatch(create))
            return false;
        else if(!before.isEmpty() && !getSelf().removeBatch(before.keySet()))
            return false;
        else
            return true;
    }

    public boolean removeByOrganizationId(String organizationId) {
        List<String> ids = baseMapper.findByOrganizationId(Arrays.asList(organizationId)).stream().map(e->e.getId()).collect(Collectors.toList());
        if(!ObjectUtils.isEmpty(ids))
            return this.removeBatch(ids);
        else
            return true;
    }

    public boolean resetByOrganizationId(String organizationId) {
        return this.update(Wrappers.<SysOrganizationalRole>lambdaUpdate().eq(SysOrganizationalRole::getOrganizationId,organizationId));
    }

    public boolean saveByOrganization(SysOrganization sysOrganization,List<SysOrganizationalRole> list) {
        if(list==null)
            return true;
        Map<String,SysOrganizationalRole> before = findByOrganizationId(sysOrganization.getId()).stream().collect(Collectors.toMap(SysOrganizationalRole::getId,e->e));
        List<SysOrganizationalRole> update = new ArrayList<>();
        List<SysOrganizationalRole> create = new ArrayList<>();

        for(SysOrganizationalRole sub:list) {
            sub.setOrganizationId(sysOrganization.getId());
            sub.setOrganization(sysOrganization);
            if(!ObjectUtils.isEmpty(sub.getId())&&before.containsKey(sub.getId())) {
                before.remove(sub.getId());
                update.add(sub);
            }
            else
                create.add(sub);
        }
        if(!update.isEmpty())
            update.forEach(item->this.getSelf().update(item));
        if(!create.isEmpty() && !getSelf().createBatch(create))
            return false;
        else if(!before.isEmpty() && !getSelf().removeBatch(before.keySet()))
            return false;
        else
            return true;
    }

    @Override
    public List<SysMember> getMember(SysOrganizationalRole et) {
        List<SysMember> list = sysMemberService.findByOrganizationalRoleId(et.getId());
        et.setMember(list);
        return list;
    }

    @Override
    public List<JSONObject> select(String sql, Map param){
        return this.baseMapper.selectBySQL(sql,param);
    }

    @Override
    @Transactional
    public boolean execute(String sql , Map param){
        if (sql == null || sql.isEmpty()) {
            return false;
        }
        if (sql.toLowerCase().trim().startsWith(SqlMethod.INSERT_ONE.getMethod())) {
            return this.baseMapper.insertBySQL(sql,param);
        }
        if (sql.toLowerCase().trim().startsWith(SqlMethod.UPDATE.getMethod())) {
            return this.baseMapper.updateBySQL(sql,param);
        }
        if (sql.toLowerCase().trim().startsWith(SqlMethod.DELETE.getMethod())) {
            return this.baseMapper.deleteBySQL(sql,param);
        }
        log.warn("暂未支持的SQL语法");
        return true;
    }

    @Override
    protected Class currentMapperClass() {
        return SysOrganizationalRoleMapper.class;
    }

    @Override
    protected Class currentModelClass() {
        return SysOrganizationalRole.class;
    }
}